package com.wy.panda.filter;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ReadListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import com.wy.panda.common.util.StringUtils;

/**
 * 
 *
 * @author WangYuan
 * @since 2020年11月5日 下午6:10:55
 */
@Order(1)
@Component
@WebFilter(filterName = "repeatReadServletRequestWrapperFilter", urlPatterns = "/**")
public class RepeatReadServletRequestWrapperFilter implements Filter {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		//判断是否是json请求，如果是的话，再封装，否则不进行封装
		String contentType = request.getContentType();
		if(StringUtils.isBlank(contentType)) {
		    chain.doFilter(request, response);
		    return;
		}
		
		if(contentType.toLowerCase().startsWith(MediaType.APPLICATION_JSON_VALUE)) {
			RepeatReadHttpServletRequestWrapper wrappedRequest = new RepeatReadHttpServletRequestWrapper((HttpServletRequest) request);
			chain.doFilter(wrappedRequest, response);
		} else {
			chain.doFilter(request, response);
		}
	}
	
	private final class RepeatReadHttpServletRequestWrapper extends HttpServletRequestWrapper {
		
		/**
		 * 存放请求的body体，以便重复读取
		 */
		private final ByteArrayOutputStream body;

		public RepeatReadHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
			super(request);
			
			ServletInputStream in = request.getInputStream();
			
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			
			byte[] tempByte = new byte[1024];
			while(in.read(tempByte) != -1) {
				out.write(tempByte);
			}
			
			body = out;
		}

		@Override
		public ServletInputStream getInputStream() throws IOException {
			
			ByteArrayInputStream inputStream = new ByteArrayInputStream(body.toByteArray());
			
			return new ServletInputStream() {
				
				@Override
				public int read() throws IOException {
					return inputStream.read();
				}
				
				@Override
				public void setReadListener(ReadListener listener) {
					throw new UnsupportedOperationException();
				}
				
				@Override
				public boolean isReady() {
					return false;
				}
				
				@Override
				public boolean isFinished() {
					return false;
				}
			};
		}

		@Override
		public BufferedReader getReader() throws IOException {
			return new BufferedReader(new InputStreamReader(getInputStream()));
		}
	}

}
